#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <arpa/inet.h>
#include <vector>
#include <stdexcept>
#include <cerrno>
#include "Message.h"
#include "ConsoleUtils.h"
#include <utfcpp/utf8.h>
#include "NetUtils.h"

using std::cout;
using std::cerr;
using std::endl;
using std::string;

int main(int argc, char *argv[]) {
    if (argc != 3) {
        cerr << "Usage: " << argv[0] << " <IP> <PORT>" << endl;
        return 1;
    }

    const char *ip = argv[1];
    int port = std::atoi(argv[2]);

    int client_fd = ::socket(AF_INET, SOCK_STREAM, 0);
    if (client_fd < 0) {
        perror("socket");
        return 1;
    }

    struct sockaddr_in server_addr;
    std::memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(port);
    server_addr.sin_addr.s_addr = inet_addr(ip);

    if (::connect(client_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) {
        perror("connect");
        ::close(client_fd);
        return 1;
    }
    cout << "--- Successfully connected to " << ip << ":" << port << " ---" << endl;
    cout << "Ready. Enter message (Format: <tag> <value>). Enter 'quit' to exit." << endl;
    cout << "tag:1 关键词候选查询  tag:2 网页查询" << endl;
    cout << "Example: 1 C++高性能服务器" << endl;
    
    string input_line;
    
    // 循环读取控制台输入
    while (cout << "> " && std::getline(std::cin, input_line)) {
        if (input_line == "quit") {
            break;
        }
        // 对用户输入进行 UTF-8 清理，防止乱码（如“工人帤½家”）导致程序崩溃
        string cleaned_input_line = clean_query(input_line);
        
        int tag = 0;
        string value;
        if (!parseInput(cleaned_input_line, tag, value)) {
            continue;
        }
        
        try {
            // 发送消息
            sendMessage(client_fd, tag, value);
            
            // 接收服务器响应
            Message response = receiveMessage(client_fd); 
            
            if(response.tag == MessageTag::KeyRecommander){
                print_candidates_from_json(cleaned_input_line, json::parse(response.value));
            }else if(response.tag == MessageTag::WebPageSearcher){
                print_json_cards(json::parse(response.value));
            }else{
                // unknown tag
            }
            
            // 刷新标准输出
            cout << std::flush;

        } catch (const std::runtime_error& e) {
            cerr << "Protocol Error: " << e.what() << endl;
            if (string(e.what()).find("Connection closed") != string::npos) {
                break; // 服务器断开连接，退出循环
            }
        }
        cout << endl;
    }

    ::close(client_fd);
    cout << "Client disconnected." << endl;
    return 0;
}